﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using DomainModel.Abstract;
using DomainModel.Entities;
using System.Web.Security;
using Microsoft.Web.Mvc.Controls;

namespace WebSite.Controllers
{
    [Authorize(Roles = "HiringManager, HiringSpecialist, Applicant")]
    public class QuestionnaireController : Controller
    {
        #region Private Variables

        private Guid userID;
        private int applicationID;
        private int jobID1;
        private int jobID2;
        private int jobID3;

        //The actual questionnaire
        List<QuestionAndAnswers> questionnaire;

        private IApplicationsRepository applicationsRepository;
        private IJobsRepository jobsRepository;
        private IPositionsRepository positionsRepository;
        private IQuestionsRepository questionsRepository;
        private IAnswersRepository answersRepository;
        private IQuestionnaireEntriesRepository questionnaireEntriesRepository;
        private IAnsweredQuestionsRepository answeredQuestionsRepository;

        #endregion

        public QuestionnaireController(IApplicationsRepository appRepo,
                                       IJobsRepository jobsRepo,
                                       IPositionsRepository posRepo,
                                       IQuestionsRepository quesRepo,
                                       IAnswersRepository ansRepo,
                                       IQuestionnaireEntriesRepository qeRepo,
                                       IAnsweredQuestionsRepository ansQuesRepo)
        {
            questionnaire = new List<QuestionAndAnswers>();          

            userID = (Guid)Membership.GetUser().ProviderUserKey;
            applicationsRepository = appRepo;
            jobsRepository = jobsRepo;
            positionsRepository = posRepo;
            questionsRepository = quesRepo;
            answersRepository = ansRepo;
            questionnaireEntriesRepository = qeRepo;
            answeredQuestionsRepository = ansQuesRepo;


            getApplicationID();
            getJobIDs();
            createQuestionnaire();
        }

        //Session Abstractions
        public int Index
        {
            get
            {
                if (HttpContext.Session["idx"] != null)
                {
                    return (int)HttpContext.Session["idx"];
                }
                else
                {
                    return -1;
                }
            }
            set
            {
                HttpContext.Session["idx"] = value;
            }
        }        
        public AnsweredQuestionsList AnsweredQuestionsList
        {
            get
            {
                if (HttpContext.Session["answers"] != null)
                {
                    return (AnsweredQuestionsList)HttpContext.Session["answers"];
                }
                else
                {
                    return null;
                }
            }
            set
            {
                HttpContext.Session["answers"] = value;
            }
        }


        public ViewResult Questionnaire()
        {
            if (HttpContext.Session["idx"] != null)
            {
                int idx = (int)HttpContext.Session["idx"];


                if (idx == questionnaire.Count)
                {
                    //Save answered questions
                    foreach (AnsweredQuestion aq in AnsweredQuestionsList.AnsweredQuestions)
                    {
                        answeredQuestionsRepository.SaveAnsweredQuestion(aq);
                    }

                    if (scoreQuestionnaire())
                    {
                        return View("ApplicationSubmitted");
                    }
                    else
                    {
                        return View("ApplicationFailed");
                    }
                }
                else
                {
                    ViewData["question"] = questionnaire[idx].Question;
                    ViewData["answers"] = questionnaire[idx].Answers;

                    //If an answer already exists at this idx, put in into the previous answer tempdata
                    try
                    {
                        //Set TempData with an answer
                        TempData["previousAnswer"] = AnsweredQuestionsList.AnsweredQuestions[Index];
                    }
                    catch
                    {
                        //This fails if there isn't an answer for this idx, which is fine
                    }
                }
            }

            return View();
        }

        /// <summary>
        /// scores the current questionnaire
        /// </summary>
        /// <returns>returns true if passing the questionnaire, or false if not passing the questionnaire</returns>
        private bool scoreQuestionnaire()
        {
            int minimumScore = 0;
            int score = 0;

            List<AnsweredQuestion> answeredQuestions = new List<AnsweredQuestion>();
            answeredQuestions.AddRange(AnsweredQuestionsList.AnsweredQuestions);
            answeredQuestions.AddRange((from aq in answeredQuestionsRepository.AnsweredQuestions
                                        where aq.ApplicationID == applicationID
                                        select aq).ToList());
            answeredQuestions = answeredQuestions.Distinct().ToList();

            foreach (AnsweredQuestion aq in answeredQuestions)
            {
                //add the minimum score to the total
                //get the questionID
                int questionID = (from qe in questionnaireEntriesRepository.QuestionnaireEntries
                                  where qe.QuestionnaireEntryID == aq.QuestionEntryID
                                  select qe.QuestionID).First();

                //get the minimum score from the question
                minimumScore += (from q in questionsRepository.Questions
                                 where q.QuestionID == questionID
                                 select q.Minimum_Score).First();

                //get the answered question's score and add it to the total
                score += (from a in answersRepository.Answers
                          where a.AnswerID == aq.AnswerID
                          select a.Value).First();
            }

            return score >= minimumScore;
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Questionnaire(FormCollection formCollection)
        {            
            if (Index == -1)
            {
                if (formCollection["Back"] != null)
                {
                    //Back was clicked
                    return RedirectToAction("Index", "Application");
                } 

                //Initialize index
                Index = 0;
                AnsweredQuestionsList = new AnsweredQuestionsList();
                AnsweredQuestionsList.AnsweredQuestions = new List<AnsweredQuestion>();               
            }
            else
            {
                if (((formCollection["AnswerRadios"] == null) && (formCollection["AnswerTextBox"] == null)) && formCollection["next"] != null)
                {
                    //No answer and next was clicked, just refresh the page
                    return Questionnaire();
                }
                else
                {
                    //Delete the answer currently at this position if there is one
                    try
                    {
                        AnsweredQuestionsList.AnsweredQuestions.RemoveAt(Index);
                    }
                    catch
                    {
                        //It doesn't matter if this happens to be out of range
                    }

                    if (formCollection["AnswerRadios"] != null || formCollection["AnswerTextBox"] != null)
                    {
                        //Save answer
                        AnsweredQuestion answeredQuestion = new AnsweredQuestion();
                        answeredQuestion.ApplicationID = applicationID;
                        answeredQuestion.QuestionEntryID = (from qe in questionnaireEntriesRepository.QuestionnaireEntries
                                                            where qe.QuestionID == Convert.ToInt16(formCollection["QuestionID"])
                                                            select qe.QuestionnaireEntryID).First();

                        if (formCollection["AnswerTextBox"] != null)
                        {
                            //It was a text question
                            answeredQuestion.TextAnswer = formCollection["AnswerTextBox"];
                            answeredQuestion.AnswerID = Convert.ToInt16(formCollection["AnswerID"]);
                        }
                        else if (formCollection["AnswerRadios"] != null)
                        {
                            //It was a radio button question               
                            answeredQuestion.AnswerID = Convert.ToInt16(formCollection["AnswerRadios"]);
                        }

                        //Add the answer to the session
                        AnsweredQuestionsList.AnsweredQuestions.Insert(Index, answeredQuestion);
                    }

                    if (formCollection["next"] != null)
                    {
                        Index = Index + 1;
                    }
                    else
                    {
                        if(Index == 0)
                        {
                            //back button was clicked and the user needs to be directed to the application
                            return RedirectToAction("Index", "Application");
                        }

                        //The back button was clicked and we need to move back a spot in the questionnaire
                        Index = Index - 1;
                    }
                }
            }

            return Questionnaire();
        }

        public ActionResult Exit()
        {
            return RedirectToAction("LogOn", "Account");
        }

        #region Private Functions
 
        private void getApplicationID()
        {
            applicationID = (from app in applicationsRepository.Applications
                             where app.UserID == userID
                             select app.ApplicationID).First();
        }

        //Fills in JobIDs
        private void getJobIDs()
        {
            int? positionID1 = 0, positionID2 = 0, positionID3 = 0;
  
            //Shouldn't ever fail
            positionID1 = (from app in applicationsRepository.Applications
                           where app.ApplicationID == applicationID
                           select app.Position1).First();

            try
            {
                positionID2 = (from app in applicationsRepository.Applications
                               where app.ApplicationID == applicationID
                               select app.Position2).First();

                positionID3 = (from app in applicationsRepository.Applications
                               where app.ApplicationID == applicationID
                               select app.Position3).First();
            }
            catch (Exception)
            {
                //If position ID2 or ID3 are still zero, then just don't do anything with them
            }

            if (positionID1 != 0)
            {
                jobID1 = (from pos in positionsRepository.Positions
                          where pos.PositionID == positionID1
                          select pos.JobID).First();
            }

            if (positionID2 != null)
            {
                jobID2 = (from pos in positionsRepository.Positions
                          where pos.PositionID == positionID2
                          select pos.JobID).First();
            }

            if (positionID3 != null)
            {
                jobID3 = (from pos in positionsRepository.Positions
                          where pos.PositionID == positionID3
                          select pos.JobID).First();
            }
        }

        //creates a usable questionnaire object
        private void createQuestionnaire()
        {
            IList<QuestionnaireEntry> listWithDuplicates = new List<QuestionnaireEntry>();

            listWithDuplicates = (from job in jobsRepository.Jobs
                                  where job.JobID == jobID1
                                  select job.QuestionnaireEntries).First();

            if (jobID2 != 0)
            {
                listWithDuplicates.Concat((from job in jobsRepository.Jobs
                                           where job.JobID == jobID2
                                           select job.QuestionnaireEntries).First());
            }

            if (jobID3 != 0)
            {
                listWithDuplicates.Concat((from job in jobsRepository.Jobs
                                           where job.JobID == jobID3
                                           select job.QuestionnaireEntries).First());
            }

            //Eliminate duplicates
            List<QuestionnaireEntry> questionnaireEntries = listWithDuplicates.Distinct().ToList();

            //Get a list of questions that have already been answered and take them out of the questionnaire entries
            List<int> answeredQuestionEntryIDs = (from aq in answeredQuestionsRepository.AnsweredQuestions
                                                  where aq.ApplicationID == applicationID
                                                  select aq.QuestionEntryID).ToList();

            foreach (int answeredQuestionEntryID in answeredQuestionEntryIDs)
            {
                for (int idx = 0; idx < questionnaireEntries.Count; ++idx)
                {
                    if (questionnaireEntries[idx].QuestionnaireEntryID == answeredQuestionEntryID)
                    {
                        questionnaireEntries.RemoveAt(idx);
                        break;
                    }
                }
            }

            //Populate questionnaire with questions, answers
            foreach (QuestionnaireEntry qe in questionnaireEntries)
            {
                Question question = (from q in questionsRepository.Questions
                                     where q.QuestionID == qe.QuestionID
                                     select q).First();
                List<Answer> answers = question.Answers.ToList();

                QuestionAndAnswers questionnaireEntry = new QuestionAndAnswers(question, answers);

                questionnaire.Add(questionnaireEntry);
            }
        }

        #endregion
    }
}
